package com.isay.frameworklib.utils;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;

import com.isay.frameworklib.application.ApplicationUtils;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import static android.os.Environment.MEDIA_MOUNTED;

/**
 * Created by cywu4 on 2018/8/21.
 */

public class FileUtils {


    private final static String DIRECTORY_NAME = "mimi";


    /**
     * 获取app文件路径
     *
     * @return
     */
    public static String getAppPath() {
        String APP_PATH = "";
        Context context = ApplicationUtils.getApplication();
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
            APP_PATH = getSdCardDirectory() + File.separator + DIRECTORY_NAME
                    + File.separator + context.getPackageName();
        } else {
            APP_PATH = context.getFilesDir().getAbsolutePath();
        }
        return APP_PATH;
    }


    /**
     * 是否有文件存储权限
     *
     * @param context
     * @return
     */
    public static boolean hasExternalStoragePermission(Context context) {
        final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
        int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
        return perm == PackageManager.PERMISSION_GRANTED;
    }


    /**
     * 获取sd卡根目录
     *
     * @return
     */
    public static String getSdCardDirectory() {
        File path = Environment.getExternalStorageDirectory();
        return path.getPath();
    }


    public static final String UTF_8 = "UTF-8";

    public static final String TAG = FileUtils.class.getSimpleName();

    public static final int MAX_BUFFER_LENGTH = 1024 * 4;

    /**
     * 創建文件
     * @param fileAbsolutePath
     */
    public static void createNewFile(String fileAbsolutePath) {
        File file = new File(fileAbsolutePath);
        createNewFile(file);
    }

    public static void createNewFile(File file) {
        if (file.exists())
            file.delete();
        File parent = file.getParentFile();
        if (!parent.exists())
            parent.mkdirs();
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static StringBuffer readText(String filePath, String decoder) {
        try {
            File file = new File(filePath);
            if (!file.exists() || !file.canRead())
                return null;

            return readText(filePath, decoder, 0, (int) file.length());

        } catch (Exception e) {
            Log.e(TAG,
                    String.format("readText Error! message:%s", e.getMessage()));
            return null;
        }
    }

    /**
     * 根据编码读取文本
     *
     * @param filePath
     *            文件路径
     * @param decoder
     *            字符集名称 例：GBK UTF-8
     * @param offset
     *            偏移量
     * @param length
     *            长度
     * @return 读取的文本
     */
    public static StringBuffer readText(String filePath, String decoder,
                                        int offset, int length) {
        FileInputStream fileInputStream = null;
        BufferedInputStream buffReader = null;

        try {
            fileInputStream = new FileInputStream(filePath);
            buffReader = new BufferedInputStream(fileInputStream);

            StringBuffer buffer = new StringBuffer();
            long size = 0;
            int readSize = 0;
            size = buffReader.available();
            if(size <= offset ) {
                return null;
            }
            if(size >= offset + length) {
                readSize = length;
            } else {
                readSize = (int)(size - offset);
            }
            byte[] bytesBuf = new byte[readSize];
            buffReader.skip(offset);
            buffReader.read(bytesBuf, 0, readSize);
            return buffer.append(new String(bytesBuf, decoder));
        } catch (Exception e) {
            Log.e(TAG,
                    String.format("readText Error!\te.getMessage:%s",
                            e.getMessage()));
        } finally {
            closeCloseable(fileInputStream);
            closeCloseable(buffReader);
        }

        return null;
    }
    /**
     * 根据路径  偏移量 长度 读取buffer
     * @Title: getBuffer
     * @param @param path
     * @param @param off
     * @param @param length
     * @return byte[]    返回类型
     * @throws
     */
    public static byte[] getBuffer(String path, int off, int length) {
        byte[] cover = null;
        FileInputStream fis = null;
        try {
            long size = 0;
            int readSize = 0;
            fis = new FileInputStream(path);
            size = fis.available();
            if(size <= off ) {
                return cover;
            }
            if(size >= off + length) {
                readSize = length;
            } else {
                readSize = (int)(size - off);
            }
            cover = new byte[readSize];
            fis.skip(off);
            fis.read(cover, 0, readSize);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeCloseable(fis);
        }

        return cover;
    }
    /**
     *根据路径读取 buffer
     * @Title: getBuffer
     * @param @param path
     * @return byte[]    返回类型
     * @throws
     */
    public static byte[] getBuffer(String path) {
        File file = new File(path);
        if(!file.exists())
            return null;
        FileInputStream fis = null;
        byte[] cover = null;
        try {
            int length = (int) file.length();
            fis = new FileInputStream(file);
            cover = new byte[length];
            fis.read(cover, 0, length);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeCloseable(fis);
        }
        return cover;
    }

    /**
     * 关闭stream or reader
     *
     * @param closeObj
     */
    public static void closeCloseable(Closeable closeObj) {
        try {
            if (null != closeObj)
                closeObj.close();
        } catch (IOException e) {
            Log.e("FileUtils Error",
                    "Method:readFile, Action:closeReader\t" + e.getMessage());
        }
    }

    public static String getContent(AssetManager assets, String fileName) {
        String ret = "";
        InputStream stream = null;
        try {
            stream = assets.open(fileName);
            ret = getContent(stream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭文件
            closeCloseable(stream);
        }
        return ret;
    }

    /**
     * 从流中, 获取数据
     * @Title: getContent
     * @param @param stream
     * @return String    返回类型
     * @throws
     */
    private static String getContent(InputStream stream) {
        String ret = "";
        try {
            int len = stream.available();
            byte[] buffer = new byte[len];
            stream.read(buffer);

            ret = new String(buffer, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ret;
    }

    /**
     * 以 <b> UTF-8 </b>格式从文件开始处写入字符串,如果文件存在，则会被重写
     *
     * @param path
     *            文件路径
     * @param content
     *            待写入的字符串
     * @return 成功时返回true，失败返回false
     */
    public static boolean writeString(String path, String content) {
        String encoding = "UTF-8";
        File file = new File(path);
        if (!file.getParentFile().exists())
            file.getParentFile().mkdirs();
        return writeString(path, content, encoding);
    }

    /**
     * 从文件开始处写入字符串,如果文件存在，则会被重写
     *
     * @param path
     *            文件路径
     * @param content
     *            待写入的字符串
     * @param encoding
     *            String转换为byte[]编码
     * @return 成功时返回true，失败返回false
     */
    public static boolean writeString(String path, String content,
                                      String encoding) {
        FileOutputStream fos = null;
        boolean result = false;
        try {
            fos = new FileOutputStream(path);
            byte[] cover = content.getBytes(encoding);
            fos.write(cover, 0, cover.length);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeCloseable(fos);
        }
        return result;
    }

    /**
     * 创建目标文件写入字节数组
     *
     * @param fileData
     *            文件字节数组
     * @return 写入成功，返回true，否则返回false
     */
    public static boolean writeBytes(String targetFilePath, byte[] fileData,boolean isDeleteMkdir) {
        boolean result = false;
        File targetFile = new File(targetFilePath);
        File parentFile = targetFile.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            targetFile.getParentFile().mkdirs();
        }else{
            if(isDeleteMkdir){
                deleteAllFiles(targetFile.getParentFile());
            }
        }
        if (targetFile.exists()) {
            targetFile.delete();
        }
        ByteArrayInputStream fosfrom = null;
        FileOutputStream fosto = null;
        try {
            fosfrom = new ByteArrayInputStream(fileData);
            fosto = new FileOutputStream(targetFile);
            byte[] buffer = new byte[1024 * 4];
            int length;
            while ((length = fosfrom.read(buffer)) != -1) {
                fosto.write(buffer, 0, length);
            }
            fosto.flush();
            result = true;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeCloseable(fosto);
            closeCloseable(fosfrom);
        }
        return result;
    }

    /**
     * 复制文件
     *
     * @param oldPath
     *            String 原文件路径
     * @param newPath
     *            String 复制后路径
     * @return
     */
    public static boolean copyFile(String oldPath, String newPath) {
        boolean result = false;
        File oldFile = new File(oldPath);
        File newFile = new File(newPath);
        if (!oldFile.exists() || !oldFile.isFile() || !oldFile.canRead()) {
            return result;
        }

        File parentFile = newFile.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            newFile.getParentFile().mkdirs();
        }
        if (newFile.exists()) {
            newFile.delete();
        }
        FileInputStream fosfrom = null;
        FileOutputStream fosto = null;
        try {
            fosfrom = new FileInputStream(oldFile);
            fosto = new FileOutputStream(newFile);
            byte[] buffer = new byte[1024 * 4];
            int length;
            while ((length = fosfrom.read(buffer)) != -1) {
                fosto.write(buffer, 0, length);
            }
            fosto.flush();
            result = true;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeCloseable(fosto);
            closeCloseable(fosfrom);
        }
        return result;
    }
    /**
     * 根据输入流 copy文件
     * @Title: copyFile
     * @param @param inputStream
     * @param @param newPath
     * @return boolean    返回类型
     * @throws
     */
    public static boolean copyFile(InputStream inputStream, String newPath) {
        boolean result = false;
        File newFile = new File(newPath);
        if (inputStream == null) {
            return result;
        }

        File parentFile = newFile.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            newFile.getParentFile().mkdirs();
        }
        if (newFile.exists()) {
            newFile.delete();
        }
        FileOutputStream fosto = null;
        try {
            fosto = new FileOutputStream(newFile);
            byte[] buffer = new byte[1024 * 4];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                fosto.write(buffer, 0, length);
            }
            fosto.flush();
            result = true;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeCloseable(fosto);
            FileUtils.closeCloseable(inputStream);
        }
        return result;
    }

    /**
     * 递归删除文件和文件夹
     *
     * @param file
     *            要删除的根目录
     */
    public static void deleteAllFiles(File file) {
        if (file.isFile()) {
            file.delete();
            return;
        }
        if (file.isDirectory()) {
            File[] childFile = file.listFiles();
            if (childFile == null || childFile.length == 0) {
                file.delete();
                return;
            }
            for (File f : childFile) {
                deleteAllFiles(f);
            }
        }
    }
    /**
     * 获取文件或者文件夹数量
     * @Title: getFileOrDirectorySize
     * @param @param f
     * @return long    返回类型
     * @throws
     */
    public static long getFileOrDirectorySize(File f)
    {
        if (f == null)
        {
            return 0;
        }

        if (!f.isDirectory())
        {
            return f.length();
        }
        else
        {
            File[] files = f.listFiles();
            if (files == null)
            {
                return 0;
            }

            long totalSize = 0;
            for (File file : files)
            {
                totalSize += getFileOrDirectorySize(file);// 递归。
            }
            return totalSize;
        }
    }
    /**
     * 删除文件夹
     * @Title: deleteDirectory
     * @param @param directory
     * @return void    返回类型
     * @throws IOException
     */
    public static void deleteDirectory(File directory) throws IOException
    {
        cleanDirectory(directory);

        if (!directory.delete())
        {
            String message = "Unable to delete directory " + directory + ".";
            throw new IOException(message);
        }
    }
    /**
     * 删除问价
     * @Title: deleteFile
     * @param @param file
     * @return void    返回类型
     * @throws IOException
     */
    public static void deleteFile(File file) throws IOException{
        if (!file.exists())
        {
//            String message = file + " does not exist";
//            throw new IllegalArgumentException(message);
            return;
        }

        if (!file.isFile())
        {
            String message = file + " is not a File";
            throw new IllegalArgumentException(message);
        }
        file.delete();
    }
    /**
     * 获取文件大小
     * @Title: getFileSize
     * @param @param file
     * @return long    返回类型
     * @throws
     */
    public static long getFileSize(File file) {
        long fileSize = 0;
        FileInputStream fis = null;
        if (file.exists()) {
            try {
                fis = new FileInputStream(file);
                fileSize = fis.available();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return fileSize;
    }
    /**
     * 清楚文件夹内容
     * @Title: cleanDirectory
     * @param @param directory
     * @return void    返回类型
     * @throws IOException
     */
    private static void cleanDirectory(File directory) throws IOException
    {
        if (!directory.exists())
        {
            String message = directory + " does not exist";
            throw new IllegalArgumentException(message);
        }

        if (!directory.isDirectory())
        {
            String message = directory + " is not a directory";
            throw new IllegalArgumentException(message);
        }

        File[] files = directory.listFiles();
        if (files == null)
        { // null if security restricted
            throw new IOException("Failed to list contents of " + directory);
        }

        IOException exception = null;
        for (File file : files)
        {
            try
            {
                forceDelete(file);
            }
            catch (IOException ioe)
            {
                exception = ioe;
            }
        }

        if (null != exception)
        {
            throw exception;
        }
    }
    /**
     * 强制删除文件
     * @Title: forceDelete
     * @param @param file
     * @return void    返回类型
     * @throws IOException
     */
    private static void forceDelete(File file) throws IOException
    {
        if (file.isDirectory())
        {
            deleteDirectory(file);
        }
        else
        {
            boolean filePresent = file.exists();
            if (!file.delete())
            {
                if (!filePresent)
                {
                    throw new FileNotFoundException("File does not exist: "
                            + file);
                }
                String message = "Unable to delete file: " + file;
                throw new IOException(message);
            }
        }
    }
    /**
     * 把Bitmap转Byte
     */
    public static byte[] bitmapToBytes(Bitmap bm){
        if(bm!=null){
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }else{
            return null;
        }

    }

}
